package com.falcon.parser;

import com.falcon.core.enums.ResponseCodeEnum;
import com.falcon.core.utils.AssertUtil;
import com.falcon.domain.vo.ApiMethodMeta;
import com.falcon.domain.vo.ControllerMeta;
import com.falcon.mvc.base.IBaseController;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author zongf
 * @date 2024-03-16
 **/
@Component
public class ControllerMetaParser {

    @Autowired
    private ControllerMethodParser controllerMethodParser;

    public ControllerMeta parseController(Class clz, boolean parseMethod, boolean parseMethodParam, boolean parseMethodReturn) {

        ControllerMeta controllerMeta = this.parserController(clz);

        if(!parseMethod){
            return controllerMeta;
        }

        List<ApiMethodMeta> apiChildren = new ArrayList<>();
        for (Method declaredMethod : clz.getDeclaredMethods()) {
            ApiMethodMeta apiMethodMeta = this.controllerMethodParser.parse(declaredMethod, parseMethodParam, parseMethodReturn);
            if (apiMethodMeta != null) {
                apiMethodMeta.setRequestUri(controllerMeta.getRequestUri() + apiMethodMeta.getRequestUri());
                apiChildren.add(apiMethodMeta);
            }
        }
        controllerMeta.setApiMethodMetas(apiChildren);

        return controllerMeta;
    }

    private ControllerMeta parserController(Class<? extends IBaseController> clz) {
        RequestMapping requestMapping = AnnotationUtils.findAnnotation(clz, RequestMapping.class);
        AssertUtil.assertNotNull(requestMapping, ResponseCodeEnum.GEN, clz.getSimpleName() + "无@RequestMapping注解");
        String uriPrefix = requestMapping.value()[0];
        String moduleName = StringUtils.substringBetween(uriPrefix, "/", "/");

        // 接口描述
        String description = "";
        Tag tag = AnnotationUtils.findAnnotation(clz, Tag.class);
        if (Objects.nonNull(tag)) {
            description = tag.description();
        }

        ControllerMeta controllerMeta = new ControllerMeta();
        controllerMeta.setModuleName(moduleName);
        controllerMeta.setRequestUri(uriPrefix);
        controllerMeta.setSimpleName(clz.getSimpleName());
        controllerMeta.setCanonicalName(clz.getCanonicalName());
        controllerMeta.setDescription(description);
        return controllerMeta;
    }

}
